/**
 * Copyright (c) 2009 Cerner Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Cerner Corporation - initial API and implementation
 */
package com.cerner.system.rest.resource.organizer;

import java.util.Set;
import java.util.concurrent.locks.Lock;

import com.cerner.system.rest.internal.arguments.NotNulls;
import com.cerner.system.rest.resource.organizer.spi.AbstractResourceController;
import com.cerner.system.rest.resource.organizer.spi.ThreadSafe;

/**
 * Internal class that builds upon the {@link MapResourceOrganizer}
 * functionality to create a thread-safe implementation of the
 * {@link ResourceController} API.
 * 
 * @author Alex Horn
 */
@ThreadSafe
class ConcurrentMapResourceController<E> extends AbstractResourceController<E> {

  /**
   * Internal API that provides a mechanism to synchronize against the map data
   * structure in which {@link MapResourceRef} objects are stored.
   * Synchronization is handled via the
   * {@link ConcurrentMapResourceOrganizer#getReadLock()} and
   * {@link ConcurrentMapResourceOrganizer#getWriteLock()} methods.
   */
  private final ConcurrentMapResourceOrganizer<E> organizer;

  /**
   * Delegate to this non-thread-safe {@link MapResourceController}
   * implementation with the appropriate locks held.
   */
  private final MapResourceController<E> controller;

  /**
   * Instantiate a thread-safe implementation of the {@link ResourceController}
   * API through which consumers can navigate, access and modify the
   * representation of a resource in a hierarchical tree structure.
   * 
   * @param controller non-thread-safe resource controller that will be
   *          protected by the synchronization policy
   * @param organizer internal API through which the underlying data structure
   *          is accessed and modified
   */
  ConcurrentMapResourceController(final MapResourceController<E> controller,
      final ConcurrentMapResourceOrganizer<E> organizer) {

    this.organizer = organizer;
    this.controller = controller;
  }

  /*
   * No lock acquisition
   */
  public java.net.URI uri() {
    return this.controller.uri();
  }

  /*
   * No lock acquisition
   */
  public ConcurrentMapResourceController<E> parent() {
    return new ConcurrentMapResourceController<E>(this.controller.parent(),
        this.organizer);
  }

  /*
   * Read lock acquisition on map data structure
   */
  public E get() {
    final Lock readLock = this.organizer.getReadLock();
    readLock.lock();
    try {
      return this.controller.get();
    } finally {
      readLock.unlock();
    }
  }

  /*
   * Write lock acquisition on map data structure
   */
  @SuppressWarnings("nls")
  public E put(final E representation) {
    NotNulls.names("representation").values(representation);

    final Lock writeLock = this.organizer.getWriteLock();
    writeLock.lock();
    try {
      return this.controller.put(representation);
    } finally {
      writeLock.unlock();
    }
  }

  /*
   * Write lock acquisition on map data structure
   */
  public Set<java.net.URI> delete() {
    final Lock writeLock = this.organizer.getWriteLock();
    writeLock.lock();
    try {
      return this.controller.delete();
    } finally {
      writeLock.unlock();
    }
  }

}
